package com.mbc.web.common.client.ui;

import java.util.ArrayList;
import java.util.Date;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.uibinder.client.UiField;
import com.mbc.web.common.shared.HttpStatus;
import com.mbc.common.entities.ApplicationItem;
import com.mbc.common.entities.LevelApplicationItem;
import com.mbc.common.entities.Role;
import com.mbc.web.common.client.ButtonActionType;
import com.mbc.web.common.client.ClientSingleton;
import com.mbc.web.common.client.CommonControllerMgr;
import com.mbc.web.common.client.CommonMessage;
import com.mbc.web.common.client.ViewUtils;
import com.mbc.web.common.client.ui.control.MButton;
import com.mbc.web.common.client.ui.control.MTextBox;
import com.mbc.web.common.shared.dto.AppItemListDTO;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;

public class FrmRole extends Composite {

	private static FrmRoleUiBinder uiBinder = GWT.create(FrmRoleUiBinder.class);
	@UiField MTextBox txtId;
	@UiField MTextBox txtName;
	@UiField Tree treeMenu;
	@UiField MButton btnSave;
	@UiField MButton btnEdit;
	@UiField MButton btnDelete;
	@UiField MButton btnReset;
	@UiField MButton btnNew;
	@UiField MButton btnBack;

	private long roleID;
	private Role role;
	private byte action_type;
	@SuppressWarnings("unused")
	private ArrayList<ApplicationItem> appItemList;
	
	interface FrmRoleUiBinder extends UiBinder<Widget, FrmRole> {
	}

	public FrmRole() {
		initWidget(uiBinder.createAndBindUi(this));
		initialize();
		onBtnNewClick(null);
	}
	
	public FrmRole(Role role) {
		initWidget(uiBinder.createAndBindUi(this));
		initialize();
		this.role = role;
	}

	public void initialize()
	{
		Scheduler.get().scheduleDeferred(new ScheduledCommand() {
			
			@Override
			public void execute() {
				txtId.setFocus(true);
			}
		});
		CommonControllerMgr.getAllAppItems(getAllAppItemsCallback());
	}
	
	private AsyncCallback<AppItemListDTO> getAllAppItemsCallback(){
		return new AsyncCallback<AppItemListDTO>() {
			
			@Override
			public void onSuccess(AppItemListDTO result) {
				if(result.getHttpStatus() == HttpStatus.OK){
					loadTree(result.getAppItemList());
					
					//if the form is showed from search view
					if(role != null){
						bindControls(role);
						enableEditable(false);
						btnSave.setEnabled(false);
						btnEdit.setEnabled(true);
						btnDelete.setEnabled(true);
						btnReset.setEnabled(false);
					}
				}
				else{
					if(result.getHttpStatus() == HttpStatus.INTERNAL_SERVER_ERROR){
						ViewUtils.showErrorMessage(CommonMessage.internal_server_error_message);
					}
				}
			}
			
			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub
				
			}
		};
	}
	
	private void loadTree(ArrayList<ApplicationItem> appItemList)
	{
		HorizontalPanel l_rootHP = new HorizontalPanel();
		final TreeItem l_rootitem = new TreeItem();
		final CheckBox l_rootchkbox = new CheckBox("Menu");
		l_rootchkbox.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				checkAllChild(l_rootitem, l_rootchkbox.getValue());
			}
		});
		l_rootHP.add(l_rootchkbox);
		l_rootitem.setWidget(l_rootHP);
		
		for (ApplicationItem appItem : appItemList) {
			if(appItem.getParentId() == 0)
			{		
				final TreeItem l_treeitem = new TreeItem();
				l_treeitem.setUserObject(appItem.getAppItemId());
				final CheckBox l_chkBox; l_chkBox = new CheckBox();
				l_chkBox.addClickHandler(new ClickHandler() {
					
					@Override
					public void onClick(ClickEvent event) {
						checkAllChild(l_treeitem, l_chkBox.getValue());
						checkParent(l_treeitem, l_chkBox.getValue());
					}
				});
				
				l_chkBox.setText(appItem.getName());
				
				HorizontalPanel l_hp = new HorizontalPanel();
				l_hp.add(l_chkBox);
				
				
				if(!appItem.getAccessCodes().equals("")){
					final Label l_lblRight = new Label("Details");
					l_lblRight.setStyleName("btn-right");
					l_lblRight.getElement().setAttribute("ac", appItem.getAccessCodes());
					l_lblRight.getElement().setAttribute("ac-v", "");
					l_hp.add(l_lblRight);
					l_lblRight.addClickHandler(new ClickHandler() {
						
						@Override
						public void onClick(ClickEvent event) {
							Label l_lbl = (Label)event.getSource();
							
							HorizontalPanel l_hp = new HorizontalPanel();
							l_hp.setSpacing(10);
							String[] l_acCodes = l_lbl.getElement().getAttribute("ac").split(",");
							for (int j = 0; j < l_acCodes.length; j++) {
								CheckBox l_chk = new CheckBox(l_acCodes[j]);
								if(l_lbl.getElement().getAttribute("ac-v").contains(l_acCodes[j]))
									l_chk.setValue(true);
								else
									l_chk.setValue(false);
								
								l_hp.add(l_chk);
							}
							
							PopupPanel l_Popup = new PopupPanel(true);
							l_Popup.setWidget(l_hp);
							l_Popup.setPopupPosition(l_lbl.getAbsoluteLeft()+50, l_lbl.getAbsoluteTop()-10);
							l_Popup.show();
							
							l_Popup.addCloseHandler(new CloseHandler<PopupPanel>() {
								
								@Override
								public void onClose(CloseEvent<PopupPanel> event) {
									HorizontalPanel l_hp = (HorizontalPanel)((PopupPanel)event.getSource()).getWidget();
									String l_acCodes = "";
									for (int j = 0; j < l_hp.getWidgetCount() ; j++) {
										CheckBox l_chk = ((CheckBox)l_hp.getWidget(j));
										if(l_chk.getValue()){
											l_acCodes += l_chk.getText() + ","; 
										}
									}
									l_acCodes = l_acCodes.substring(0, l_acCodes.length() - 1);
									l_lblRight.getElement().setAttribute("ac-v", l_acCodes);
								}
							});
						}
					});
					
					l_hp.setSpacing(3);
				}	
				
				l_treeitem.setWidget(l_hp);
				
				l_rootitem.addItem(l_treeitem);
				loadTreeNode(appItem.getAppItemId(), appItemList, l_treeitem);
				l_treeitem.setState(true);
			}
		}
		
		l_rootitem.setState(true);
		treeMenu.addItem(l_rootitem);
	}
	
	private void loadTreeNode(long parentID, ArrayList<ApplicationItem> appItemList, TreeItem parentItem)
	{
		for (ApplicationItem appItem : appItemList) {
			if(parentID == appItem.getParentId())
			{	
				HorizontalPanel l_hp = new HorizontalPanel();
				final TreeItem l_treeitem = new TreeItem();
				l_treeitem.setUserObject(appItem.getAppItemId());
				CheckBox l_chkBox = new CheckBox();
				l_chkBox.setText(appItem.getName());
				l_chkBox.addClickHandler(new ClickHandler() {
					
					@Override
					public void onClick(ClickEvent event) {
						checkAllChild(l_treeitem,((CheckBox)event.getSource()).getValue());
						checkParent(l_treeitem, ((CheckBox)event.getSource()).getValue());
					}
				});
				
				l_hp.add(l_chkBox);
				if(!appItem.getAccessCodes().equals("")){
					final Label l_lblRight = new Label("Details");
					l_lblRight.setStyleName("btn-right");
					l_lblRight.getElement().setAttribute("ac", appItem.getAccessCodes());
					l_lblRight.getElement().setAttribute("ac-v", "");
					l_hp.add(l_lblRight);
					l_lblRight.addClickHandler(new ClickHandler() {
						
						@Override
						public void onClick(ClickEvent event) {
							Label l_lbl = (Label)event.getSource();
							
							HorizontalPanel l_hp = new HorizontalPanel();
							l_hp.setSpacing(10);
							String[] l_acCodes = l_lbl.getElement().getAttribute("ac").split(",");
							for (int j = 0; j < l_acCodes.length; j++) {
								CheckBox l_chk = new CheckBox(l_acCodes[j]);
								if(l_lbl.getElement().getAttribute("ac-v").contains(l_acCodes[j]))
									l_chk.setValue(true);
								else
									l_chk.setValue(false);
								
								l_hp.add(l_chk);
							}
							
							PopupPanel l_Popup = new PopupPanel(true);
							l_Popup.setWidget(l_hp);
							l_Popup.setPopupPosition(l_lbl.getAbsoluteLeft()+50, l_lbl.getAbsoluteTop()-10);
							l_Popup.show();
							
							l_Popup.addCloseHandler(new CloseHandler<PopupPanel>() {
								
								@Override
								public void onClose(CloseEvent<PopupPanel> event) {
									HorizontalPanel l_hp = (HorizontalPanel)((PopupPanel)event.getSource()).getWidget();
									String l_acCodes = "";
									for (int j = 0; j < l_hp.getWidgetCount() ; j++) {
										CheckBox l_chk = ((CheckBox)l_hp.getWidget(j));
										if(l_chk.getValue()){
											l_acCodes += l_chk.getText() + ","; 
										}
									}
									if(!l_acCodes.equals("")){
										l_acCodes = l_acCodes.substring(0, l_acCodes.length() - 1);
										l_lblRight.getElement().setAttribute("ac-v", l_acCodes);
									}
								}
							});
						}
					});
					
					l_hp.setSpacing(3);
				}
				
				l_treeitem.setWidget(l_hp);
				
				parentItem.addItem(l_treeitem);
				loadTreeNode(appItem.getAppItemId(), appItemList, l_treeitem);
				l_treeitem.setState(true);
			}
		}
	}
	
	private void bindControls(Role role)
	{
		txtId.setText(role.getRoleName());
		txtName.setText(role.getDescription());
		roleID = role.getRoleID();
		if(role.getLevelAppItemList().size() > 0)
			((CheckBox)((HorizontalPanel)treeMenu.getItem(0).getWidget()).getWidget(0)).setValue(true);
		bindMenuTree(treeMenu.getItem(0), role.getLevelAppItemList());
	}
	
	private void clear(){
		txtId.setText("");
		txtName.setText("");
		roleID = 0;
		ViewUtils.clearRequiredNotifications();
		role = null;
		appItemList = new ArrayList<ApplicationItem>();
	}
	
	private void bindMenuTree(TreeItem parentItem, ArrayList<LevelApplicationItem> lvlAppItemList)
	{
		for (int i = 0; i < parentItem.getChildCount(); i++) {
			TreeItem l_child = parentItem.getChild(i);
			CheckBox l_chkbox = (CheckBox)((HorizontalPanel)l_child.getWidget()).getWidget(0);
			l_chkbox.setValue(false);
			for (LevelApplicationItem l_lvlAppItem : lvlAppItemList) {
				Long l_appid = Long.parseLong(parentItem.getChild(i).getUserObject().toString());
				if(l_appid == l_lvlAppItem.getAppitemId())
				{
					l_chkbox.setValue(true);
					if(!l_lvlAppItem.getAccessCodes().equals(""))
						((Label)((HorizontalPanel)l_child.getWidget()).getWidget(1)).getElement().setAttribute("ac-v", l_lvlAppItem.getAccessCodes());
					break;
				}
			}
			
			bindMenuTree(parentItem.getChild(i), lvlAppItemList);
		}
	}
	
	private Role bindRole()
	{
		Role l_role  = new Role();
		l_role.setRoleID(roleID);
		l_role.setCreated_Date(new Date());
		l_role.setDescription(txtName.getText());
		l_role.setModule("");
		l_role.setRoleName(txtId.getText());
		l_role.setTopLevel(0);
		l_role.setUpdated_Date(new Date());
		return l_role;
	}
	
	private void bindLevelAppItemList(TreeItem parentItem, ArrayList<LevelApplicationItem> lvlAppItemList)
	{
		CheckBox l_chk;
		for (int i = 0; i < parentItem.getChildCount(); i++) {
			l_chk = (CheckBox)((HorizontalPanel)parentItem.getChild(i).getWidget()).getWidget(0);
			
			if(l_chk.getValue())
			{
				LevelApplicationItem l_lvlAppItem = new LevelApplicationItem();
				
				l_lvlAppItem.setAppitemId(Long.parseLong(parentItem.getChild(i).getUserObject().toString()));
				l_lvlAppItem.setRoleId(roleID);
				
				HorizontalPanel l_hp = (HorizontalPanel)parentItem.getChild(i).getWidget();
				String l_acCodes = "";
				if(l_hp.getWidgetCount() > 1)
				{
					l_acCodes = ((Label)l_hp.getWidget(1)).getElement().getAttribute("ac-v");
				}
				l_lvlAppItem.setAccessCodes(l_acCodes);
				lvlAppItemList.add(l_lvlAppItem);
			}
			
			bindLevelAppItemList(parentItem.getChild(i), lvlAppItemList);
		}
	}
	
	private void enableEditable(boolean enabled)
	{
		txtId.setEnabled(enabled);
		txtName.setEnabled(enabled);
		
		if(treeMenu.getItemCount() > 0)
		{
			((CheckBox)((HorizontalPanel)treeMenu.getItem(0).getWidget()).getWidget(0)).setEnabled(enabled);
			enableTree(treeMenu.getItem(0), enabled);
		}
	}
	
	private void enableTree(TreeItem parentItem, boolean flag)
	{
		CheckBox l_chkbox;
		for (int i = 0; i < parentItem.getChildCount(); i++) {
			HorizontalPanel l_hp = (HorizontalPanel)parentItem.getChild(i).getWidget();
			l_chkbox = (CheckBox)l_hp.getWidget(0);
			if(l_hp.getWidgetCount() > 1)
				((Label)l_hp.getWidget(1)).setVisible(flag);
			l_chkbox.setEnabled(flag);
			enableTree(parentItem.getChild(i), flag);
		}
		
	}
	
	private void checkAllChild(TreeItem parentItem, boolean flag)
	{
		CheckBox l_chkbox;
		for (int i = 0; i < parentItem.getChildCount(); i++) {
			l_chkbox = (CheckBox)((HorizontalPanel)parentItem.getChild(i).getWidget()).getWidget(0);
			l_chkbox.setValue(flag);
			checkAllChild(parentItem.getChild(i), flag);
		}
	}
	
	private void checkParent(TreeItem childItem, boolean flag)
	{
		if(childItem.getParentItem() != null)
		{
			CheckBox l_chkbox = (CheckBox)((HorizontalPanel)childItem.getParentItem().getWidget()).getWidget(0);
			
			if(!flag)
			{
				if(childItem.getParentItem() != null)
				{
					TreeItem l_TreeItem = childItem.getParentItem();
					boolean l_issiblingcheck = false;
					CheckBox l_innerchk;
					for (int i = 0; i < l_TreeItem.getChildCount(); i++) {
						if(!l_TreeItem.getChild(i).getUserObject().toString().equals(childItem.getUserObject().toString()))
						{
							l_innerchk = (CheckBox)l_TreeItem.getChild(i).getWidget();
							if(l_innerchk.getValue())
							{
								l_issiblingcheck = true;
								break;
							}
						}
					}
					if(!l_issiblingcheck)
					{
						l_chkbox.setValue(flag);
						checkParent(childItem.getParentItem(),flag);
					}
				}
			}
			else
			{
				l_chkbox.setValue(flag);
				checkParent(childItem.getParentItem(), flag);
			}
			
		}
	}
	
	private AsyncCallback<Integer> actionCallback()
	{
		return new AsyncCallback<Integer>() {
			
			@Override
			public void onSuccess(Integer result) {
				ViewUtils.stopAjaxLoader();
				if(result == HttpStatus.OK){
					switch (action_type) {
					case ButtonActionType.action_save:
						ViewUtils.showSuccessMessage(CommonMessage.saved_message);
						break;
					case ButtonActionType.action_delete:
						ViewUtils.showSuccessMessage(CommonMessage.deleted_message);
						break;
					}
					ClientSingleton.changeView(new SearchRole());
				}
				else{
					switch (result) {
					case HttpStatus.INTERNAL_SERVER_ERROR:
						ViewUtils.showErrorMessage(CommonMessage.internal_server_error_message);
						break;
					case HttpStatus.BAD_REQUEST:
						ViewUtils.showErrorMessage(CommonMessage.getAlreadyExistedMessage("Role Name(" + txtId.getText() + ")"));
						break;
					case HttpStatus.FORBIDDEN:
						ViewUtils.showErrorMessage(CommonMessage.getDataCannotDeleteMessage("Role Name(" + txtId.getText() + ")"));
						break;
					}
				}
			}
			
			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub
				
			}
		};
	}
	
	@UiHandler("btnNew")
	void onBtnNewClick(ClickEvent event) {
		clear();
		
		enableEditable(true);
		
		txtId.setFocus(true);
		btnSave.setEnabled(true);
		btnEdit.setEnabled(false);
		btnDelete.setEnabled(false);
		btnReset.setEnabled(false);
		
		if(treeMenu.getItemCount() >0)
		{
			((CheckBox)((HorizontalPanel)treeMenu.getItem(0).getWidget()).getWidget(0)).setValue(false);
			checkAllChild(treeMenu.getItem(0), false);
		}
	}
	
	@UiHandler("btnSave")
	void onBtnSaveClick(ClickEvent event) {
		if(ViewUtils.isValidate())
		{
			action_type = ButtonActionType.action_save;
			ArrayList<LevelApplicationItem> l_lvlAppItemList = new ArrayList<LevelApplicationItem>();
			bindLevelAppItemList(treeMenu.getItem(0), l_lvlAppItemList);
			Role l_role = bindRole();
			l_role.setLevelAppItemList(l_lvlAppItemList);
			ViewUtils.startAjaxLoader(CommonMessage.saving_message);
			if(roleID == 0)
				CommonControllerMgr.createRole(l_role, actionCallback());
			else
				CommonControllerMgr.updateRole(l_role, actionCallback());
		}
		else{
			ViewUtils.showErrorMessage("");
		}
	}
	
	@UiHandler("btnEdit")
	void onBtnEditClick(ClickEvent event) {
		if(roleID != 0)
		{
			btnReset.setEnabled(true);
			btnSave.setEnabled(true);
			btnEdit.setEnabled(false);
			btnNew.setEnabled(false);
			enableEditable(true);
			txtName.setFocus(true);
			txtId.setEnabled(false);
		}
	}
	
	@UiHandler("btnDelete")
	void onBtnDeleteClick(ClickEvent event) {
		if(roleID != 0)
		{
			ViewUtils.showConfirm(CommonMessage.delete_confirm_message, new CloseHandler<PopupPanel>() {
				
				@Override
				public void onClose(CloseEvent<PopupPanel> event) {
					if(ViewUtils.isAlertYes()){
						action_type = ButtonActionType.action_delete;
						ViewUtils.startAjaxLoader(CommonMessage.deleting_message);
						CommonControllerMgr.deleteRole(roleID, actionCallback());
					}
				}
			});
		}
	}
	@UiHandler("btnReset")
	void onBtnResetClick(ClickEvent event) {
		bindControls(role);
		enableEditable(false);
		btnReset.setEnabled(false);
		btnSave.setEnabled(false);
		btnEdit.setEnabled(true);
		btnNew.setEnabled(true);
		if(role.getLevelAppItemList().size() > 0)
			((CheckBox)((HorizontalPanel)treeMenu.getItem(0).getWidget()).getWidget(0)).setValue(true);
		bindMenuTree(treeMenu.getItem(0), role.getLevelAppItemList());
	}
	
	@UiHandler("btnBack")
	void onBtnBackClick(ClickEvent event) {
		ClientSingleton.changeView(new SearchRole());
	}
}
